package pl.edu.agh.student.janikhankus.tree;

import java.util.ArrayList;
import java.util.List;

import pl.edu.agh.student.janikhankus.earley.ParseProduction;

/**
 * Class which represents production.
 * 
 * @author Jaroslaw Janik
 */
public class Production implements Comparable<Object>{
	
	private NonTerminal left;
	private ArrayList<Symbol> right = new ArrayList<Symbol>();
	private double probability;
	private boolean isTemporary = false;
	
	/**
	 * Gets nonterminal on the left side of production.
	 * 
	 * @return Nonterminal on the left side of production.
	 */
	public NonTerminal getLeft() {
		return left;
	}
	
	/**
	 * Sets nonterminal on the left side of production.
	 * 
	 * @param left Nonterminal to set.
	 */
	public void setLeft(NonTerminal left) {
		this.left = left;
	}

	/**
	 * Gets right side of production.
	 * 
	 * @return List of productions.
	 */
	public ArrayList<Symbol> getRight() {
		return right;
	}

	/**
	 * Sets right side of production.
	 * 
	 * @param right List of productions to set.
	 */
	public void setRight(ArrayList<Symbol> right) {
		this.right = right;
	}
	
	/**
	 * Mark production as temporary.
	 */
	public void markAsTemporary() {
		isTemporary = true;
	}
	
	/**
	 * Checks whether production is temporary.
	 * @return
	 */
	public boolean isTemporary() {
		return isTemporary;
	}

	/**
	 * Gets production's probability.
	 * 
	 * @return Production's probability.
	 */
	public double getProbability() {
		return probability;
	}

	/**
	 * Sets production's probability.
	 * 
	 * @param probability Probability to set.
	 */
	public void setProbability(double probability) {
		this.probability = probability;
	}
	
	@Override
	public int compareTo(Object o){
		if(!(o instanceof Production)){
			return 1;
		}
		Production p = (Production) o;
		List<Symbol> tmpSymbolList = p.getRight();
		List<Symbol> tmpThisSymbolList = this.getRight(); 
		if(this == p){
			return 0;
		}
		if(tmpSymbolList.size() != tmpThisSymbolList.size()){
			return 1;
		}
		for(int i=0; i<tmpThisSymbolList.size(); i++){
			if(!tmpSymbolList.get(i).getName().equals(tmpThisSymbolList.get(i).getName())){
				return 1;
			}
		}
		NonTerminal thisLeft = this.getLeft();
		NonTerminal pLeft = p.getLeft();
		if(thisLeft == null || pLeft == null){
			if(thisLeft != pLeft){
				return 1;
			}
		}
		else{
			if(!thisLeft.getName().equals(pLeft.getName())){
				return 1;
			}
		}
		return 0;
	}
	
	@Override
	public int hashCode()
	{
		return (new Integer(4)).hashCode();
	}
	
	@Override
	public boolean equals(Object o){
		if(!(o instanceof Production)){
			return false;
		}
		Production p = (Production) o;
		List<Symbol> tmpSymbolList = p.getRight();
		List<Symbol> tmpThisSymbolList = this.getRight(); 
		if(this == p){
			return true;
		}
		if(tmpSymbolList.size() != tmpThisSymbolList.size()){
			return false;
		}
		for(int i=0; i<tmpThisSymbolList.size(); i++){
			if(!tmpSymbolList.get(i).getName().equals(tmpThisSymbolList.get(i).getName())){
				return false;
			}
		}
		NonTerminal thisLeft = this.getLeft();
		NonTerminal pLeft = p.getLeft();
		if(thisLeft == null || pLeft == null){
			if(thisLeft != pLeft){
				return false;
			}
		}
		else{
			if(!thisLeft.getName().equals(pLeft.getName())){
				return false;
			}
		}
		return true;
	}	
}